package com.qiji.video.util;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

import static com.qiji.video.util.RedisConstants.*;

/**
 * 定时任务，整合排行榜
 */
@Service
@Slf4j
public class TaskService {
    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    /**
     * 2. 定时5秒钟，模拟微博的热度刷新（例如模拟点赞 收藏 评论的热度值更新）
     * 3. 定时1小时合并统计 天、周、月的排行榜。
     */
    @PostConstruct
    public void init(){
        log.info("启动初始化 .......");
        // 定时5秒钟，模拟微博的热度刷新（例如模拟点赞 收藏 评论的热度值更新）
        new Thread(()->this.refreshDataHour()).start();
        // 定时1小时合并统计 天、周、月的排行榜。
        new Thread(()->this.refreshData()).start();
    }

    private void refreshData() {
        while(true){
            //刷新当天的统计数据
            this.refreshDay();
            //刷新7天统计数据
            this.refreshWeek();
            //刷新30天统计数据
            this.refreshMonth();
            // TODO 在分布式系统中，建议用xxl-job来实现定时
            try {
                Thread.sleep(1000*60*60);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public void refreshDay(){
        long hour=System.currentTimeMillis()/(1000*60*60);
        List<String> otherKeys=new ArrayList<>();
        //算出近24小时内的key
        for(int i=1;i<23;i++){
            String  key=Video_Click_KEY_HOUR+(hour-i);
            otherKeys.add(key);
        }
        //把当前的时间key，并且把后推23个小时，共计近24小时，求出并集存入Constants.DAY_KEY中
        //redis ZUNIONSTORE 求并集
        this.stringRedisTemplate.opsForZSet().unionAndStore(Video_Click_KEY_HOUR+hour,otherKeys,Video_Click_KEY_DAY);

        //设置当天的key 40天过期，不然历史数据浪费内存
        for(int i=0;i<24;i++){
            String  key=Video_Click_KEY_HOUR+(hour-i);
            this.stringRedisTemplate.expire(key,40, TimeUnit.DAYS);
        }
        log.info("天刷新完成..........");
    }
    /**
     *刷新7天的统计数据
     */
    public void refreshWeek(){
        long hour=System.currentTimeMillis()/(1000*60*60);
        List<String> otherKeys=new ArrayList<>();
        //算出近7天内的key
        for(int i=1;i<24*7-1;i++){
            String  key=Video_Click_KEY_HOUR+(hour-i);
            otherKeys.add(key);
        }
        //把当前的时间key，并且把后推24*7-1个小时，共计近24*7小时，求出并集存入Constants.WEEK_KEY中
        this.stringRedisTemplate.opsForZSet().unionAndStore(Video_Click_KEY_HOUR+hour,otherKeys,Video_Click_KEY_WEEK);

        log.info("周刷新完成..........");
    }

    /**
     *刷新30天的统计数据
     */
    public void refreshMonth(){
        long hour=System.currentTimeMillis()/(1000*60*60);
        List<String> otherKeys=new ArrayList<>();
        //算出近30天内的key
        for(int i=1;i<24*30-1;i++){
            String  key=Video_Click_KEY_HOUR+(hour-i);
            otherKeys.add(key);
        }
        //把当前的时间key，并且把后推24*30个小时，共计近24*30小时，求出并集存入Constants.MONTH_KEY中
        this.stringRedisTemplate.opsForZSet().unionAndStore(Video_Click_KEY_HOUR,otherKeys,Video_Click_KEY_Month);
        log.info("月刷新完成..........");
    }

    private void refreshDataHour() {
        while(true){
            this.refreshWeek();

            try {
                Thread.sleep(1000*60*2);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    

}
